package com.ogier.app.jeu.pieces;

import java.util.ArrayList;

import com.ogier.app.jeu.Case;
import com.ogier.app.jeu.export.ExportFormat;

/**
 * @author gogier
 *
 */
/**
 * @author gogier
 * 
 */
public class Roi extends Piece {

	public final static int	ROC_PETIT						= 0;
	public final static int	ROC_GRAND						= 1;

	boolean					aDejaEteEnEchec;
	ArrayList<Piece>		listeDesPiecesAttaquantes;
	ArrayList<Case>			listeCasesSurTrajectoireAttaque	= new ArrayList<Case>();

	Tour					tour1;
	Tour					tour2;

	public Roi(int couleur) {
		super(couleur);
		aDejaEteEnEchec = false;
		type = Piece.PIECE_ROI;
	}

	public Roi(int couleur, Case laCase) {
		super(couleur, laCase);
		type = Piece.PIECE_ROI;
		aDejaEteEnEchec = false;
	}

	public Roi(int couleur, Case laCase, Tour t1, Tour t2) {
		this(couleur, laCase);
		tour1 = t1;
		tour2 = t2;
		listeDesPiecesAttaquantes = new ArrayList<Piece>();
		listeCasesSurTrajectoireAttaque = new ArrayList<Case>();
	}

	public ArrayList<Case> getCasesDeplacementPossible() {
		return getCasesDeplacementPossibleSpecifique();
	}

	public ArrayList<Case> getCasesDeplacementPossibleSpecifique() {
		ArrayList<Case> resultat = new ArrayList<Case>();

		// On vérifie ses diagonnales et ses horizontales et verticales

		// 4 Diagonales + 4 directions
		//
		int[] d1 = { -1, -1, 1, 1, -1, 0, 1, 0 };
		int[] d2 = { -1, 1, -1, 1, 0, 1, 0, -1 };

		for (int i = 0; i < 8; i++) {
			int decal = 1;
			int val1 = decal * d1[i];
			int val2 = decal * d2[i];
			Case caseTmp = position.getLePlateau().getCase(position, val1, val2);
			if (caseTmp != null) {

				if (caseTmp.getPiece() == null) {
					// S'il n'y a pas de pièce
					resultat.add(caseTmp);
				} else {
					if (caseTmp.getPiece() != null) {
						// S'il y a une pièce
						if (caseTmp.getPiece().getCouleur() != couleur) {
							resultat.add(caseTmp);
						}
					}
				}

			}
		}

		/* Condition pour pouvoir roquer :
		o Le roi et la tour ne doivent pas avoir bougŽ.
		o Le roi ne doit pas �tre en Žchec ni passer par une case
		en Žchec.
		o Aucune pi�ce ne doit �tre prŽsente entre le roi et la tour concernŽe
		*/
		if (!aDejaEteEnEchec && !aDejaBouge) {
			if (!tour1.aDejaBouge) {
				// la tour et le roi n'ont pas bougŽ, on vŽrifie les cases entre
				// les deux
				boolean pasDePiece = true;
				for (int i = this.getPosition().getPositionY() - 1; i > tour1.getPosition().getPositionY(); i--) {
					if (lePlateau.getCase(this.getPosition().getPositionX(), i).getPiece() != null) {
						pasDePiece = false;
						break;
					}
				}
				if (pasDePiece == true) {
					// Rock possible :
					Case positionRoi = lePlateau.getCase(tour1.getPosition().getPositionX(), tour1.getPosition()
							.getPositionY() + 1);
					resultat.add(positionRoi);
				}
			}
			if (!tour2.aDejaBouge) {
				// la tour et le roi n'ont pas bougŽ, on vŽrifie les cases entre
				// les deux
				boolean pasDePiece = true;
				for (int i = this.getPosition().getPositionY() + 1; i < tour2.getPosition().getPositionY(); i++) {
					if (lePlateau.getCase(this.getPosition().getPositionX(), i).getPiece() != null) {
						pasDePiece = false;
						break;
					}
				}
				if (pasDePiece == true) {
					// Rock possible :
					Case positionRoi = lePlateau.getCase(tour2.getPosition().getPositionX(), tour2.getPosition()
							.getPositionY() - 1);
					resultat.add(positionRoi);
				}
			}

		}

		// Retirer les positions ou le roi serait en echec
		ArrayList<Case> resultatFinal = new ArrayList<Case>();
		for (Case c : resultat) {
			// Si la case n'est pas attaquée alors on l'ajoute à la liste finale
			if (!c.isPiecesAttaquantsCetteCase(lePlateau.getCouleurJoueurEnAttente())) {
				resultatFinal.add(c);
			}
		}

		return resultatFinal;
	}

	/**
	 * Analyse si le roi est en position d'echec
	 */
	public boolean checkIfEchec() {

		// on part du roi
		// On vérifie, les diag, hor, vert... et les positions des cavaliers

		// Condition :
		// le roi est en lien direct avec la piece
		// Si sur diago : fou ou reine
		// si sur hor/ver : tour ou reine
		// si sur pos cavalier : cavalier

		ArrayList<Integer> typeAttaquant = new ArrayList<Integer>();
		listeCasesSurTrajectoireAttaque = new ArrayList<Case>();
		listeDesPiecesAttaquantes = new ArrayList<Piece>();
		ArrayList<Case> casesSurTrajectoireAttaque_tmp = new ArrayList<Case>();

		// La diago

		int[] d1 = { -1, -1, 1, 1 };
		int[] d2 = { -1, 1, -1, 1 };
		int[] d3 = { -1, 0, 1, 0 };
		int[] d4 = { 0, 1, 0, -1 };
		int[] d5 = { -2, -2, 2, 2, -1, 1, -1, 1 };
		int[] d6 = { -1, 1, -1, 1, 2, 2, -2, -2 };

		typeAttaquant.add(Piece.PIECE_FOU);
		typeAttaquant.add(Piece.PIECE_REINE);

		for (int i = 0; i < 4; i++) {
			int decal = 1;
			int val1 = decal * d1[i];
			int val2 = decal * d2[i];
			Case caseTmp = position.getLePlateau().getCase(position, val1, val2);
			while (caseTmp != null) {

				// Cette case est potentiellement sur la trajectoire d'attaque
				casesSurTrajectoireAttaque_tmp.add(caseTmp);

				if (caseTmp.getPiece() != null) {
					// S'il y a une pièce
					if (caseTmp.getPiece().getCouleur() != couleur) {
						// Si c'est une couleur adverse
						// Si fou ou reine
						if (typeAttaquant.contains(caseTmp.getPiece().getType())) {
							// C'est une attaque : En echec
							listeDesPiecesAttaquantes.add(caseTmp.getPiece());
							// On ajoute toutes les cases potentielles dans les
							// cases réellement sur la trajectoire
							listeCasesSurTrajectoireAttaque.addAll(casesSurTrajectoireAttaque_tmp);
							break;
						}
					} else {
						// C'est une pièce qui protège on peut passer à la suite
						break;
					}

				}

				decal++;
				val1 = decal * d1[i];
				val2 = decal * d2[i];
				caseTmp = position.getLePlateau().getCase(position, val1, val2);
			}
			// On remet à jour les cases potentielles pour une nouvelle
			// trajectoire
			casesSurTrajectoireAttaque_tmp.clear();
		}

		// hori / verti
		typeAttaquant.clear();
		typeAttaquant.add(Piece.PIECE_TOUR);
		typeAttaquant.add(Piece.PIECE_REINE);

		for (int i = 0; i < 4; i++) {
			int decal = 1;
			int val1 = decal * d3[i];
			int val2 = decal * d4[i];
			Case caseTmp = position.getLePlateau().getCase(position, val1, val2);
			while (caseTmp != null) {

				// Cette case est potentiellement sur la trajectoire d'attaque
				casesSurTrajectoireAttaque_tmp.add(caseTmp);

				if (caseTmp.getPiece() != null) {
					// S'il y a une pièce
					if (caseTmp.getPiece().getCouleur() != couleur) {
						// Si c'est une couleur adverse
						// Si fou ou reine
						if (typeAttaquant.contains(caseTmp.getPiece().getType())) {
							// C'est une attaque : En echec
							listeDesPiecesAttaquantes.add(caseTmp.getPiece());
							// On ajoute toutes les cases potentielles dans les
							// cases réellement sur la trajectoire
							listeCasesSurTrajectoireAttaque.addAll(casesSurTrajectoireAttaque_tmp);
							break;
						}
					} else {
						// C'est une pièce qui protège on peut passer à la suite
						break;
					}

				}

				decal++;
				val1 = decal * d3[i];
				val2 = decal * d4[i];
				caseTmp = position.getLePlateau().getCase(position, val1, val2);
			}
			// On remet à jour les cases potentielles pour une nouvelle
			// trajectoire
			casesSurTrajectoireAttaque_tmp.clear();
		}

		// cavalier
		// Pas de trajectoire possible.
		typeAttaquant.clear();
		typeAttaquant.add(Piece.PIECE_CAVALIER);

		for (int i = 0; i < 8; i++) {
			int decal = 1;
			int val1 = decal * d5[i];
			int val2 = decal * d6[i];
			Case caseTmp = position.getLePlateau().getCase(position, val1, val2);
			if (caseTmp != null) {

				if (caseTmp.getPiece() != null) {
					// S'il y a une pièce
					if (caseTmp.getPiece().getCouleur() != couleur) {
						// Si c'est une couleur adverse
						// Si fou ou reine
						if (typeAttaquant.contains(caseTmp.getPiece().getType())) {
							// C'est une attaque : En echec
							listeDesPiecesAttaquantes.add(caseTmp.getPiece());
							// On ajoute la case potentielle
							listeCasesSurTrajectoireAttaque.add(caseTmp);

						}
					} else {
						// C'est une pièce qui protège on peut passer à la suite
						break;
					}

				}

			}
		}

		return estEnEchec();

	}

	public void setEnEchec(boolean estEnEchec) {
		// Si on demande de positionner à non alors on vide la liste des pieces
		// attaquantes
		if (!estEnEchec) {

			listeDesPiecesAttaquantes.clear();

		} else {

			// Si on défini qu'il y a echec alors on indique que le roi a déjà
			// été en échec
			aDejaEteEnEchec = true;
		}
	}

	public boolean isADejaEteEnEchec() {
		return aDejaEteEnEchec;
	}

	public boolean estEnEchec() {
		return (listeDesPiecesAttaquantes.size() > 0);
	}

	public int getNbAttaquants() {
		return listeDesPiecesAttaquantes.size();
	}

	/**
	 * @return the listeDesPiecesAttaquantes
	 */
	public ArrayList<Piece> getListeDesPiecesAttaquantes() {
		return listeDesPiecesAttaquantes;
	}

	/**
	 * @param listeDesPiecesAttaquantes the listeDesPiecesAttaquantes to set
	 */
	public void setListeDesPiecesAttaquantes(ArrayList<Piece> listeDesPiecesAttaquantes) {
		this.listeDesPiecesAttaquantes = listeDesPiecesAttaquantes;
	}

	/**
	 * @return the listeCasesSurTrajectoireAttaque
	 */
	public ArrayList<Case> getListeCasesSurTrajectoireAttaque() {
		return listeCasesSurTrajectoireAttaque;
	}

	/**
	 * @param listeCasesSurTrajectoireAttaque the
	 *            listeCasesSurTrajectoireAttaque to set
	 */
	public void setListeCasesSurTrajectoireAttaque(ArrayList<Case> listeCasesSurTrajectoireAttaque) {
		this.listeCasesSurTrajectoireAttaque = listeCasesSurTrajectoireAttaque;
	}

	public String toString() {
		return toString(ExportFormat.ECRAN);
	}

	public String toString(int format) {
		String res;
		// Format
		switch (format) {

			case (ExportFormat.PNG):
				res = "K";
			default:
				if (couleur == Piece.BLANC)
					res = "R";
				else
					res = "r";
		}

		return res;
	}

	public Piece getTour1() {
		return tour1;
	}

	public Piece getTour2() {
		return tour2;
	}
}
